import java.io.*;
import java.util.*;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;


/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WGL
 * Date: 2022-10-28
 * Time: 15:42
 */
public class Dao {

    //    初始化专业数据
    public void getSpeciallity(Speciality[] Tar) throws IOException {
        int n = 0;
        BufferedReader reader = new BufferedReader(new FileReader("specialityInf2022.txt"));
        while (n<Tar.length) {
            Tar[n] = new Speciality();
            String[] rec = reader.readLine().split(" ");
            Tar[n].academy = rec[0];
            Tar[n].name = rec[1];
            int recuritNum = Integer.parseInt(rec[2]);
            Tar[n].numToRecruit = recuritNum;
            Tar[n].recruitedStudent = new Student[recuritNum];
            Tar[n].exactNum = Integer.parseInt(rec[3]);
            Tar[n].lowestRank = Integer.parseInt(rec[4]);
            n++;
        }
        System.out.println("==========================================================================");
    }

    //    初始化学生数据
    public void initStudent(Student[] toTest, Stack<Integer> stack, Stack<Integer> stack1) {
        Random random = new Random();
        for (int i = 0; i < toTest.length; i++) {
            toTest[i] = new Student(random, stack, i, stack1);
        }
    }

    public void collectRank(Student[] students) {
        try (Workbook workbook = new SXSSFWorkbook();
             FileOutputStream out = new FileOutputStream("E:\\RecruitStudentWithExcel\\rank.xlsx")) {

            // 创建新的工作簿
            Sheet sheet = workbook.createSheet("num");
            for (int i = 0; i < students.length; i++) {
                Row row = sheet.createRow(i);
                Cell cell = row.createCell(0);
                cell.setCellValue(students[i].rank);
            }
            workbook.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //     得到专业的各指标
    public void getSpecialityFeatrues(Speciality[] Tar) throws IOException {
        Academy[] academies = new Academy[17];
        BufferedReader reader = new BufferedReader(new FileReader("academyInf2024.txt"));
        for (int i = 0; i < academies.length; i++) {
            academies[i] = new Academy();
            String[] name = reader.readLine().split(" ");
            academies[i].name = name[0];
            for (int j = 0; j < 4; j++) {
                if (j==4){
                    System.out.println(" ");
                }
                String feature = name[j + 1];
                academies[i].featrues[j] = (Float.parseFloat(feature) / 100);
            }
        }
        System.out.println("=========================================================================");
        for (int i = 0; i < Tar.length; i++) {
            for (Academy academy : academies) {
                if (Tar[i].academy.equals(academy.name)) {
                    Tar[i].setFeatures(academy.featrues.clone());
                }
            }
        }



    }

    public void sortStudent(Student[] students) {
//        分而治之，循环为每次总数除二
        for (int i = students.length / 2; i > 0; i /= 2) {
//            循环分治的每一个分组
            for (int j = i; j < students.length; j++) {
                int index = j;
                Student temp = students[index];
//                比较每一组的值
                if (students[index].rank < students[index - i].rank) {
//                    如果比前面小就把前面的数值往后移，将合适的数值插入
                    while (index - i > 0 && temp.rank < students[index - i].rank) {
                        students[index] = students[index - i];
                        index -= i;
                    }
                    students[index] = temp;
                }
            }
        }
    }




    public void getSpecialityToStudent(Student[] Tar, Speciality[] Source, ArrayList<String[]> specialityRecord) throws IOException {
        Random random = new Random();
        for (int i = 0; i < Tar.length; i++) {
            Tar[i].judgeSpeciality(random, Source);
//            Tar[i].judgeSpecialityFrom2021(i, specialityRecord, Source);
            Tar[i].quickSortFavouriteSpeciality(Tar[i].favouriteSpeciality, 0, Tar[i].numOfFavouriteSpeciality - 1);
//            System.out.println(" ");
        }
    }


    public void getEnrollmentTeam(ArrayList<EnrollmentTeam> enrollmentTeams, Speciality[] specialities, String[] names,int choice) throws IOException {
        switch (choice){
            case 1:
//                学院
                for (int i = 0; i < 17; i++) {
                    EnrollmentTeam enrollmentTeam = new EnrollmentTeam();
                    enrollmentTeam.name = names[i];
                    enrollmentTeams.add(enrollmentTeam);
                    enrollmentTeam.possibilityToAdjust = 1;
                }
                for (int i = 0; i < specialities.length; i++) {
                    for (int j = 0; j < enrollmentTeams.size(); j++) {
                        if (specialities[i].academy.equals(enrollmentTeams.get(j).name)) {
                            enrollmentTeams.get(j).specialities.add(specialities[i]);
                        }
                    }
                }
                break;
            case 2:
                ////        小组
                BufferedReader reader = new BufferedReader(new FileReader("teamInf2022.txt"));
                for (int i = 0; i < 9; i++) {
                    EnrollmentTeam team = new EnrollmentTeam();
                    String[] rec = reader.readLine().split(" ");
                    team.name = rec[0];
                    for (int k = 1; k < rec.length-1; k++) {
                        for (int j = 0; j < specialities.length; j++) {
                            if(rec[k].equals(specialities[j].name)){
                                team.specialities.add(specialities[j]);
                            }
                        }
                    }
                    team.possibilityToAdjust = Double.parseDouble(rec[rec.length-1]);
                    team.specialtyNum = rec.length-2;
                    enrollmentTeams.add(team);
                }
                reader.close();
                break;
            case 3:
                EnrollmentTeam enrollmentTeam = new EnrollmentTeam();
                enrollmentTeam.specialities.addAll(Arrays.asList(specialities));
                enrollmentTeams.add(enrollmentTeam);
                enrollmentTeam.specialtyNum = specialities.length;
                enrollmentTeam.possibilityToAdjust = 1;
                enrollmentTeam.name = "大组";
                break;
            default:

        }


//        大组



    }


    public void studentRegisterToTeam(Student[] students, ArrayList<EnrollmentTeam> teams) {
        for (int i = 0; i < students.length; i++) {
//            System.out.print("序号: "+i+" ");
            students[i].getEnrollmentTeam(teams);

        }
    }





    public void judgeStudentAdjustment(Student[] students) {
        for (int i = 0; i < students.length; i++) {
            students[i].judgeIsWillingToAdjust();
//
        }
    }

    public void officiallyRecruitStudent(Student[] students) {
        for (int i = 1; i < students.length; i++) {
            for (int j = 0; j < students[i].getNumOfEnrollmentTeamNum; j++) {
                ArrayList<Speciality> tmp = students[i].specialityToRecruitInTeam.get(students[i].registeredTeam.get(j));
                for (int k = 0; k < tmp.size(); k++) {
                    tmp.get(k).addStudent(students[i]);
                    if (students[i].isRecruitedGdut) break;
                }
                if (students[i].isRecruitedGdut) break;
            }
        }
    }



    public void exportDataToExcel(Student[] students, Speciality[] tar) {
        long begin = System.currentTimeMillis(); //获取当前时间(毫秒)

        //超大excel文件写入使用SXSSFWorkbook对象
        try (Workbook workbook = new SXSSFWorkbook();
             FileOutputStream out = new FileOutputStream("E:\\RecruitStudent5.0\\Data.xlsx")) {

            // 创建新的工作簿
            Sheet sheet = workbook.createSheet("1");

            // 获取格式编码值
            DataFormat format = workbook.createDataFormat();
//            short dateFormat = format.getFormat("");
//            short monyFormat = format.getFormat("#,###");

            // 创建日期格式对象
//            CellStyle dateCellType = workbook.createCellStyle();
//            dateCellType.setDataFormat(dateFormat);

            // 创建红包格式对象
            CellStyle moneyCellType = workbook.createCellStyle();
//            moneyCellType.setDataFormat(monyFormat);

            for (int i = 0; i < students.length; i++) {

                String name = students[i].personality;
                Row row = sheet.createRow(i + 1);

                Cell cell0 = row.createCell(0); // 性格
                cell0.setCellValue(name);

                Cell cell1 = row.createCell(1); // 排名
                cell1.setCellValue(students[i].rank);

                Cell cell2 = row.createCell(2); // 第一偏好专业
//                cell2.setCellStyle(dateCellType);
                if (students[i].favouriteSpeciality[0].tar == null) {
                    cell2.setCellValue(" ");
                } else {
                    cell2.setCellValue(students[i].favouriteSpeciality[0].tar.name);
                }
                Cell cell3 = row.createCell(3); // 第一负偏好专业
                cell3.setCellStyle(moneyCellType);
                if (students[i].hateSpeciality[0].tar == null) {
                    cell3.setCellValue(" ");
                } else {
                    cell3.setCellValue(students[i].hateSpeciality[0].tar.name);
                }
                for (int j = 0; j < students[i].expectationToSpeciality.length; j++) {
                    Cell cell = row.createCell(4 + j);
                    cell.setCellValue(students[i].expectationToSpeciality[j]);
                }

            }
            sheet = workbook.createSheet("2");
            for (int i = 0; i < tar.length; i++) {
                int numF = 0;
                int numH = 0;
                for (int j = 0; j < students.length; j++) {
                    if (students[j].favouriteSpeciality[0].tar == null) continue;
                    if (students[j].favouriteSpeciality[0].tar.name.equals(tar[i].name)) {
                        numF++;
                    }

                }
                Row row = sheet.createRow(i);
                Cell cell = row.createCell(0);
                cell.setCellValue(tar[i].name);
                cell = row.createCell(1);
                cell.setCellValue(numF);
                cell = row.createCell(2);
                cell.setCellValue(numH);
            }
            workbook.write(out);

            long end = System.currentTimeMillis();
            System.out.println("耗时" + (end - begin) + "毫秒"); //计算时间差

        } catch (IOException e) {
            e.printStackTrace();
        }
        try (Workbook workbook = new SXSSFWorkbook();
             FileOutputStream out = new FileOutputStream("E:\\RecruitStudent5.0\\SpecialityFeatures.xlsx")) {

            Sheet sheet = workbook.createSheet("1");

            Row row1 = sheet.createRow(0);
            Cell cell = row1.createCell(1);
            cell.setCellValue("工作满意度");
            cell = row1.createCell(2);
            cell.setCellValue("专业相关度");
            cell = row1.createCell(3);
            cell.setCellValue("职业期待吻合度");
            cell = row1.createCell(4);
            cell.setCellValue("母校满意度");
            cell = row1.createCell(5);
            cell.setCellValue("真实平均排名");


            for (int i = 0; i < tar.length; i++) {

                String name = tar[i].name;
                Row row = sheet.createRow(i + 1);

                Cell cell0 = row.createCell(0); // 性格
                cell0.setCellValue(name);

                for (int j = 0; j < tar[i].Features.length; j++) {
                    cell0 = row.createCell(j + 1);
                    cell0.setCellValue(tar[i].Features[j]);
                }
                cell0 = row.createCell(5);
                cell0.setCellValue(tar[i].exactNum);

            }
            workbook.write(out);

            long end = System.currentTimeMillis();
            System.out.println("耗时" + (end - begin) + "毫秒"); //计算时间差

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void adjustSpecialityFeatures(Speciality[] specialities, String[] name) {
//        adjustFeaturesInAcademy(specialities, name);
        featuresNormalization(specialities);
//        for (int i = 0; i < specialities.length; i++) {
//            System.out.println(specialities[i].toString());
//        }
    }

    private void featuresNormalization(Speciality[] specialities) {
        double yMin, yMax, xMax, xMin;
        yMin = 0.3;
        yMax = 1;
        xMax = xMin = specialities[0].Features[0];
        for (int i = 0; i < specialities.length; i++) {
            for (int j = 0; j < specialities[i].Features.length; j++) {
                if (xMax < specialities[i].Features[j]) {
                    xMax = specialities[i].Features[j];
                }
                if (xMin > specialities[i].Features[j]) {
                    xMin = specialities[i].Features[j];
                }
            }
        }
        for (int i = 0; i < specialities.length; i++) {
            for (int j = 0; j < specialities[i].Features.length; j++) {
                double x = specialities[i].Features[j];
                specialities[i].Features[j] = (float) (yMin + ((yMax - yMin) / (xMax - xMin)) * (x - xMin));
            }
        }
    }


    private void adjustF(ArrayList<Speciality> specialities, int sum) {
        for (Speciality s :
                specialities) {
            float tag = (float) sum / s.exactNum;
            if (tag > 1) continue;
            for (int i = 0; i < s.Features.length; i++) {
                s.Features[i] *= tag;
            }
        }
    }

    public void isRecruited(Student[] students) {
        for (int i = 0; i < students.length; i++) {
            if (students[i].isRecruitedGdut) {
                System.out.println("1");
            } else {
                System.out.println("0");
            }
        }
    }

    public void recruitSecondRound(Student[] students) {
        for (int i = 0; i < students.length; i++) {
            if (!students[i].isRecruitedGdut) {
                for (int j = 0; j < students[i].getNumOfEnrollmentTeamNum; j++) {
                    if (students[i].tagToAdjustment[j]) {
                        for (int k = 0; k < students[i].registeredTeam.get(j).specialities.size(); k++) {
                            if (students[i].registeredTeam.get(j).specialities.get(k).numToRecruit >
                                    students[i].registeredTeam.get(j).specialities.get(k).queue.size()) {
                                students[i].registeredTeam.get(j).specialities.get(k).addStudent(students[i]);
                            }
                            if (students[i].isRecruitedGdut) break;
                        }
                        if (students[i].isRecruitedGdut) break;
                    }
                }
                if (students[i].isRecruitedGdut) continue;
            }
        }
    }

    public void abortTeam(Student[] students) {
        for (int i = 0; i < students.length; i++) {
            students[i].abortTeam();
            System.out.println(" ");
        }
    }


    public ArrayList<String[]> getLikeSpecialityReal(Speciality[] specialities) throws IOException {
        ArrayList<String[]> ret = new ArrayList<>();
        BufferedReader reader = new BufferedReader(new FileReader("likeSpecialityReal.txt"));
        for (int i = 0; i < 6717; i++) {
            String[] tag = reader.readLine().split("\t");
            ArrayList<String> tmp = new ArrayList<>();
            for (int j = 0; j < tag.length; j++) {
                for (int k = 0; k < specialities.length; k++) {
                    if (tag[j].equals(specialities[k].name)) {
                        tmp.add(tag[j]);
                    }
                }
            }
            String[] rec = new String[tmp.size()];
            for (int j = 0; j < tmp.size(); j++) {
                rec[j] = tmp.get(j);
            }
            ret.add(rec);
        }
        return ret;
    }

    public void sortSpecialityByAvgRank(Speciality[] specialities, int low, int high) {
        int i, j;
        Speciality temp, t;
        if (low > high) {
            return;
        }
        i = low;
        j = high;
        //temp就是基准位
        temp = specialities[low];

        while (i < j) {
            //先看右边，依次往左递减
            while (temp.exactNum <= specialities[j].exactNum && i < j) {
                j--;
            }
            //再看左边，依次往右递增
            while (temp.exactNum >= specialities[i].exactNum && i < j) {
                i++;
            }
            //如果满足条件则交换
            if (i < j) {
                t = specialities[j];
                specialities[j] = specialities[i];
                specialities[i] = t;
            }

        }
        //最后将基准为与i和j相等位置的数字交换
        specialities[low] = specialities[i];
        specialities[i] = temp;
        //递归调用左半数组
        sortSpecialityByAvgRank(specialities, low, j - 1);
        //递归调用右半数组
        sortSpecialityByAvgRank(specialities, j + 1, high);
    }

    public void sortSpecialityInTeam(ArrayList<EnrollmentTeam> team) {
        for (int i = 0; i < team.size(); i++) {
            Collections.sort(team.get(i).specialities);
        }
    }

    public void getSpecialityRankInTeam(Speciality[] specialities) {
        for (int i = 0; i < specialities.length; i++) {
            specialities[i].rankINTeam = i + 1;
        }
    }

    public void studentGetSpecialityInTeam(Student[] students) {
        for (int i = 0; i < students.length; i++) {
            for (int j = 0; j < students[i].getNumOfEnrollmentTeamNum; j++) {
                ArrayList<Speciality> tag = findSpecialityInTeam(students[i], students[i].registeredTeam.get(j).specialities);
                students[i].specialityToRecruitInTeam.put(students[i].registeredTeam.get(j), tag);
            }
        }
    }

    private ArrayList<Speciality> findSpecialityInTeam(Student student, ArrayList<Speciality> specialitiesInTeam) {
//        Random random = new Random();
//        int tag = random.nextInt(5000);
//        ArrayList<Speciality> ret = new ArrayList<>();
//        for (int i = 0; i < student.numOfFavouriteSpeciality; i++) {
//            ret.add(student.favouriteSpeciality[i].tar);
//        }
//        int pos = list.indexOf(student.favouriteSpeciality[student.numOfFavouriteSpeciality - 1].tar);
//        for (int i = pos + 1; i < list.size() && ret.size() < 6; i++) {
//            if (student.rank + tag < list.get(i).exactNum) {
//                ret.add(list.get(i));
//            }
//        }
//        return ret;
        Random random = new Random();
        int tag = random.nextInt(5000);
        ArrayList<Speciality> tmpLike = new ArrayList<>();
        ArrayList<Speciality> tmpElseHigh = new ArrayList<>();
        ArrayList<Speciality> tmpElseLow = new ArrayList<>();
        ArrayList<Speciality> ret = new ArrayList<>();
        for (int i = 0; i < specialitiesInTeam.size(); i++) {
            for (int j = 0; j < student.numOfFavouriteSpeciality; j++) {
                if (specialitiesInTeam.get(i).name.equals(student.favouriteSpeciality[j].tar.name)) {
                    tmpLike.add(specialitiesInTeam.get(i));
                } else {
                    if (specialitiesInTeam.get(i).exactNum < student.rank) {
                        tmpElseHigh.add(specialitiesInTeam.get(i));
                    } else {
                        tmpElseLow.add(specialitiesInTeam.get(i));
                    }
                }
            }
        }
        Speciality rush = findLowestPos(tmpElseHigh);
        Speciality down = findHighestMark(student,tmpElseLow);
       if(tmpLike.size()<=5 && rush!=null){
           ret.add(rush);
       }
        ret.addAll(tmpLike);
//        if(ret.size()<=5 && down!=null){
//            ret.add(down);
//        }
        return ret;
    }

    private static Speciality findLowestPos(ArrayList<Speciality> specialities) {
        if (specialities.size() == 0) return null;
        int tag = specialities.get(0).exactNum;
        int pos = 0;
        for (int i = 0; i < specialities.size(); i++) {
            if (specialities.get(i).exactNum > tag) {
                tag = specialities.get(i).exactNum;
                pos = i;
            }
        }
        return specialities.get(pos);
    }

    private static Speciality findHighestMark(Student student, ArrayList<Speciality> specialities) {
        if (specialities.size() == 0) return null;
        double markTmp = 0;
        int pos = 0;
        for (int i = 0; i < specialities.size(); i++) {
            if(markTmp<student.getMarkToSpeciality(specialities.get(i))){
                markTmp = student.getMarkToSpeciality(specialities.get(i));
                pos = i;
            }
        }
        return specialities.get(pos);
    }

    public void countRankNotRecruit(ArrayList<Integer> list,Student[] students){
        for (int i = 1; i < students.length; i++) {
            if(!students[i].isRecruitedGdut){
                list.add(students[i].rank);
            }
        }
        try (Workbook workbook = new SXSSFWorkbook();
             FileOutputStream out = new FileOutputStream("E:\\RecruitStudent5.0\\notRecruit.xlsx")) {
            Sheet sheet = workbook.createSheet("1");
            Row row = sheet.createRow(0);
            Cell cell = row.createCell(0);
            cell.setCellValue("未录取学生排名分布情况");
            for (int i = 0; i < list.size(); i++) {
                 row = sheet.createRow(i+1);
                 cell = row.createCell(0);
                 cell.setCellValue(list.get(i));
            }
            workbook.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}




